[小ネタ]dbtでクエリ実行結果を変数として扱う方法
さがらです。
小ネタなのですが、dbtでクエリ結果を変数として扱う方法について本記事でまとめます。
※下記のStack Overflowの記事の最も投票数が高い投稿を実際に試してみた内容となります。
dbtでクエリ結果を変数として扱う方法
早速結論ですが、下記のように記述をすればOKです。
{%- call statement('get_query_result', fetch_result=True) -%}
select * from customers
{%- endcall -%}
{%- set var_result = load_result('get_query_result')['data'][0][0] -%}
この上で、dbtのModel上で参照したい場合には下記のように記述をすればOKです。[0][0]
とすると、1列目の1行目の値を返します。1つ目の[0]
が何番目のレコードか、2つ目の[0]
何個目のカラムか、を指定する必要があります。
{%- call statement('get_query_result', fetch_result=True) -%}
select * from customers
{%- endcall -%}
{%- set var_result = load_result('get_query_result')['data'][0][0] -%}
select
{{ var_result }} as result
また、日付の値を変数として取得してクエリ上でその変数を日付として扱いたい場合は'
で変数を囲んで一度明示的に文字列としてから型変更をしてあげる必要があります。
{%- call statement('get_query_result', fetch_result=True) -%}
select * from customers
{%- endcall -%}
{%- set var_result = load_result('get_query_result')['data'][0][3] -%}
select
cast('{{ var_result }}' as date) as result
裏話
なんでこんな小ネタを投稿したのかというと、Snowflake×dbtでのIncremental Modelの実装時に下記の記事のエラーに遭遇したためです…
私はこの記事の解決方法ではうまくいかなかったため、本記事で記したように変数化することで解決しました。(以下は実装したコードのイメージです。)
-- 現在のテーブルから最新日時を変数として取得
{% if is_incremental() %}
{%- call statement('get_latest_time', fetch_result=True) -%}
select coalesce(max(update_at), '1900-01-01') from {{ this }}
{%- endcall -%}
{%- set var_latest_time = load_result('get_latest_time')['data'][0][0] -%}
{% endif %}
-----------
-- 中略
-----------
-- 取得した変数を差分検知の処理に適用
{% if is_incremental() %}
where update_at > to_timestamp('{{ var_latest_time }}')
{% endif %}